home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Screen savers / PeekaBoo module ƒ / Peek-a-Boo.c < prev    next >
Encoding:
Text File  |  1993-10-03  |  18.6 KB  |  600 lines  |  [TEXT/KAHL]

  1. // ver 1.1.1 changes - 3 Oct 93
  2. //        - added Kramer sound to rsrc file
  3. //        - fixed RangedRdm() code and update the controlvalues to match as it is running
  4. // ver 1.1 changes     -    26 Sept 93
  5. //        - did the GetGWorldPixMap() in the slide_up and down routines
  6. //         I had forgotten to do that in a case
  7. //        - added a control checkbox for randomness and code
  8. //         - added a STR#/tVal to put a message underneath the faces menu (in the .rsrc)    
  9.  
  10. #include <QuickDraw.h>
  11. #include <Memory.h>
  12. #include <Resources.h>
  13.  
  14. #include <QDoffscreen.h>
  15.  
  16. #include "GraphicsModule_Types.h"
  17. #include "Sounds.h"
  18.  
  19. unsigned short RangedRdm( unsigned short min, unsigned short max );
  20.  
  21. // these are the functs that need defined ...
  22. OSErr DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params);
  23. OSErr DoClose(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);
  24. OSErr DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);
  25. OSErr DoDrawFrame(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);
  26. OSErr DoSetUp(RgnHandle blankRgn, short message, GMParamBlockPtr params);
  27.  
  28. // extra ones
  29. OSErr DoSelected(RgnHandle blankRgn, short message, GMParamBlockPtr params);
  30. OSErr DoAboutBox(RgnHandle blankRgn, short message, GMParamBlockPtr params);
  31.  
  32.  
  33. #define ONE_KNOCK_SND    256
  34. #define BASE_PICTID        127            // this is 1 less than the starting ID number (128)
  35.  
  36. #define NUMPICTS        26    
  37.  
  38. // states for the simple state machine ...
  39. #define STATE_DOWN            0
  40. #define STATE_GOING_UP        1
  41. #define STATE_UP            2
  42. #define STATE_LOOKING        3
  43. #define STATE_GOING_DOWN    4
  44. #define RANDOM_CHECK        5        // new
  45.  
  46.  
  47. // this is borrowed from the example code from Bouncing Ball ...
  48. /* some macros to simplify synchronizing to the vertical retrace. */
  49. #define SynchFlag(m) (params->monitors->monitorList[m].synchFlag)
  50. #define SynchVBL(m) synchFlag = &SynchFlag(m); *synchFlag = false; while(!*synchFlag);
  51.  
  52.  
  53.  
  54. typedef struct infostruct {
  55.     Boolean        soundAvailable;            // do we have sound?
  56.     Handle        oneKnockSound;            // one knock sound
  57.     GWorldPtr    gMyOffG;                // offscreen graphics world
  58.  
  59. // the face stuff
  60.     PicHandle    thePict;                // the face to slide up and down
  61.     PicHandle    eyes, eyesleft, eyesright;    // the eyes to slide left/right
  62.     Point        eyesPt;                    // where they eyes are supposed to be drawn
  63.     Handle        faceSound;                // a sound associated with a face
  64.     short        thePictNumber;            // the number of the picture we're using
  65.     Rect        theRect;                // rects for the sliding face
  66.     short        thePictWidth;            // time saving info on rect's width
  67.     short        thePictHeight;            // "    "        "        "       height
  68.  
  69.     SoundInfoHandle    soundInfo;            // AD sound info handle
  70.     Rect        theScreen;                // the monitor's screen rect
  71.     long        nextSoundTick;            // last tick when a the knocking sound was played
  72.     short        state;                    // the state we're in
  73. } infostruct, *infostructPtr, **infostructHandle;
  74.  
  75.  
  76.  
  77. // some prototypes ...
  78. void do_some_knocking(infostructPtr info, GMParamBlockPtr params);
  79. void slide_picture_up(infostructPtr info, GMParamBlockPtr params);
  80. void slide_picture_down(infostructPtr info, RgnHandle blankRgn, GMParamBlockPtr params);
  81. void slide_eyes_around(infostructPtr info, GMParamBlockPtr params);
  82.  
  83. //////////////////////////////////////////////////////////////////////////////////////
  84. // this is the first funct called by AD ... we need to allocate and initialize here
  85. OSErr
  86. DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params) {
  87.  
  88. // ERROR MESSAGES ....
  89.     StringPtr         memoryMessage = (StringPtr)"\pmodule: Not enough memory!";
  90.     StringPtr         loadMessage = (StringPtr)"\pmodule: Could not load pict!";
  91.     StringPtr        offscreenMessage = (StringPtr)"\pmodule: Offscreen Bitmap failed!";
  92.     StringPtr        colorMessage = (StringPtr)"\pmodule: Must have color!";
  93.     StringPtr        menuMessage = (StringPtr)"\pmodule: Failed to get MENU!!";
  94. // the variables ...
  95.     Handle             h;
  96.     Handle            tempHandle;
  97.     infostructPtr    mystorage;
  98.     GWorldPtr        currPort;        // something to save the port + device
  99.     GDHandle        currDev;
  100.     PixMapHandle    pixBase;
  101.     
  102.     // lets ensure we're running on a screen of some depth ... (yes? no? do we care?)
  103.     // no ... I don't care ...just go on and run and let it look wierd
  104.     // but we do need some color Quickdraw - I haven't put in the B&W offscreen 
  105.     // routines to do offscreen bitmaps 
  106.     if (!params->colorQDAvail) {
  107.         BlockMove(colorMessage, params->errorMessage, 1 + colorMessage[0]);
  108.         return ModuleError;                    // could not allocate space
  109.     }
  110.     
  111.     // allocate space here for my structure - whatever it may be
  112.     h = NewHandle( sizeof(infostruct) );    
  113.     
  114.     if (h == (Handle)nil) {
  115.         *storage = nil;
  116.         h = nil;
  117.         BlockMove(memoryMessage, params->errorMessage, 1 + memoryMessage[0]);
  118.         return ModuleError;                    // could not allocate space
  119.     }
  120.     
  121.     // Randomize...
  122.     params->qdGlobalsCopy->qdRandSeed = TickCount();
  123.     
  124.     // handle pointer to have
  125.     *storage = h;
  126.     
  127.     // lock down our storage so we can refer to it by pointer safely
  128.     MoveHHi(h);
  129.     HLock(h);    
  130.     
  131.     mystorage = (infostructPtr) *h;
  132.  
  133. ///////// load the sounds ...
  134.     // do we have sound support?
  135.     mystorage->soundAvailable = (params->systemConfig & SoundAvailable) != 0;
  136.  
  137.     if (mystorage->soundAvailable) {
  138.     
  139.         /* load the resources for our  sounds. */
  140.         mystorage->oneKnockSound = GetResource('snd ', ONE_KNOCK_SND);
  141.     
  142.         /* to use the sound functions in AD 2.0u we must pass in "params" */
  143.         mystorage->soundInfo = OpenSound(params);
  144.     }
  145.  
  146. // check randomness first ...
  147.     if (params->controlValues[1]) {        // We're random
  148.         MenuHandle theMenu;
  149.         short rCount, i;
  150.         
  151.         // how many menu items are there?
  152.         theMenu = (MenuHandle)GetResource('MENU', 1002);
  153.         if (theMenu == (MenuHandle)nil) {
  154.             DebugStr("\pBig problems!");
  155.         }
  156.         rCount = CountMItems( theMenu);                        // how many picts?
  157.         // pick one
  158.         params->controlValues[2] = mystorage->thePictNumber = RangedRdm(1, rCount);
  159.         // by setting the controlValues[2] parameter ... the menu changes in demo mode!
  160.         // Neat!
  161.             
  162.         ReleaseResource( (Handle)theMenu);
  163.     } else {
  164.         mystorage->thePictNumber = params->controlValues[2];
  165.     }
  166.         
  167.     mystorage->thePict = 
  168.             (PicHandle)GetResource('PICT', BASE_PICTID + mystorage->thePictNumber);
  169.  
  170.     if (mystorage->thePict == (PicHandle)nil) {
  171.         DoClose( h, (RgnHandle) nil, (GMParamBlockPtr) nil);
  172.         BlockMove(loadMessage, params->errorMessage, 1 + loadMessage[0]);
  173.         return ModuleError;                        // could not load pict
  174.     }
  175.         
  176.  
  177. ////// get it's sound ... if it's possible
  178.         mystorage->faceSound = GetResource('snd ', BASE_PICTID + mystorage->thePictNumber);
  179.  
  180. ////// get the eye pictures ... if it's possible
  181.     mystorage->eyes = (PicHandle)GetResource('PICT', 
  182.             ((BASE_PICTID + mystorage->thePictNumber) * 10) + 1);
  183.     mystorage->eyesleft = (PicHandle)GetResource('PICT', 
  184.             ((BASE_PICTID + mystorage->thePictNumber) * 10) + 2);
  185.     mystorage->eyesright = (PicHandle)GetResource('PICT', 
  186.             ((BASE_PICTID + mystorage->thePictNumber) * 10) + 3);
  187.  
  188. ////// get the eye Point resource ... if it's possible
  189.     if ( (tempHandle = GetResource('eyes', (BASE_PICTID + mystorage->thePictNumber))) != 
  190.             (Handle)nil) {
  191.         PointPtr p;
  192.         
  193.         p = (PointPtr)(*tempHandle);
  194.         mystorage->eyesPt = (*p);
  195.         ReleaseResource( tempHandle);
  196.     } else 
  197.         mystorage->eyesPt.h = mystorage->eyesPt.v = -1;
  198.     
  199. ///////
  200.     mystorage->theRect =  (*mystorage->thePict)->picFrame;
  201.     mystorage->thePictWidth = mystorage->theRect.right - mystorage->theRect.left;
  202.     mystorage->thePictHeight = mystorage->theRect.bottom - mystorage->theRect.top;
  203.     
  204.     
  205. //////////////////////////////////////////////////////////////////
  206. // lets setup the offscreen world
  207.     // save the current info
  208.     GetGWorld(&currPort,&currDev);
  209.     
  210.     // create the offscreen world (with the bounds of the picture)
  211.     if (NewGWorld(&(mystorage->gMyOffG), 0, &mystorage->theRect, nil, nil, 0) != noErr) {
  212.         DoClose( h, (RgnHandle) nil, (GMParamBlockPtr) nil);
  213.         BlockMove(offscreenMessage, params->errorMessage, 1 + offscreenMessage[0]);
  214.         return ModuleError;            
  215.     }
  216.     // keep it from moving
  217.     pixBase = GetGWorldPixMap( mystorage->gMyOffG );
  218.     LockPixels (pixBase);
  219.     
  220.     // point to the offscreen world
  221.     SetGWorld ((mystorage->gMyOffG), nil);
  222.     
  223.     // draw it
  224.     DrawPicture( mystorage->thePict, &mystorage->theRect );
  225.     // could release the resource now, you know.
  226.  
  227.     // done drawing, set the world back 
  228.     SetGWorld (currPort, currDev);
  229.     
  230.     // unlock those puppies
  231.     UnlockPixels (pixBase);
  232. //////////////////////////////////////////////////////////////////
  233.  
  234.     
  235.     mystorage->theScreen = params->monitors->monitorList[0].bounds;
  236.     mystorage->nextSoundTick = 0;
  237.     
  238.     mystorage->state = STATE_DOWN;
  239.  
  240.     HUnlock(h);
  241.     
  242.     return noErr;
  243. }
  244.  
  245. //////////////////////////////////////////////////////////////////////////////////////
  246. // the screen saver has been awakened! time to ditch the storage and wave goodbye
  247. OSErr 
  248. DoClose(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params) {
  249.     
  250.     infostructPtr    mystorage;
  251.     
  252.     HLock(storage);
  253.     
  254.     mystorage = (infostructPtr)*storage;
  255.     
  256.     if (mystorage->soundAvailable) {
  257.         CloseSound( mystorage->soundInfo, params->sndChannel);
  258.         
  259.         // knocking sound
  260.         if (mystorage->oneKnockSound != (Handle)nil)
  261.             ReleaseResource(mystorage->oneKnockSound);
  262.  
  263.         // the face's sound
  264.         if (mystorage->faceSound != (Handle)nil)
  265.             ReleaseResource(mystorage->faceSound);
  266.  
  267.     }
  268.     
  269.     
  270.     ReleaseResource( (Handle)mystorage->thePict);
  271.     // release the eye picts ... if they're there
  272.     if (mystorage->eyes != (PicHandle)nil)
  273.         ReleaseResource( (Handle)mystorage->eyes);
  274.     if (mystorage->eyesleft != (PicHandle)nil)
  275.         ReleaseResource( (Handle)mystorage->eyesleft);
  276.     if (mystorage->eyesright != (PicHandle)nil)
  277.         ReleaseResource( (Handle)mystorage->eyesright);
  278.         
  279.         
  280.     DisposeGWorld( mystorage->gMyOffG);
  281.     HUnlock(storage);
  282.     DisposHandle( storage);
  283.     return noErr;
  284. }
  285.  
  286.  
  287.  
  288. //////////////////////////////////////////////////////////////////////////////////////
  289. // make the screen go black
  290. OSErr
  291. DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params) {
  292.  
  293.     FillRgn(blankRgn, params->qdGlobalsCopy->qdBlack);
  294.     return noErr;
  295.  
  296. }
  297.  
  298. //////////////////////////////////////////////////////////////////////////////////////
  299. // this is the workhorse routine. It does the continual screen work to make
  300. // this screen saver what it is.
  301. OSErr 
  302. DoDrawFrame(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params) {
  303.     infostructPtr    info;
  304.  
  305.  
  306.     HLock(storage);
  307.     info = (infostructPtr)*storage;
  308.  
  309.     // pay attention to the controls in demo mode ...
  310.     // - the menu (2) is different than the picture number ... someone must
  311.     // have changed the menu! -  so restart the module
  312.     if ( (params->controlValues[2]) != info->thePictNumber) {
  313.         DoClose(storage, blankRgn, params);    // ditch the storage
  314.         return RestartMe;                    // tell AD to reinit us
  315.     }
  316.  
  317.     // when sufficient time has passed ... the face should peep up
  318.     
  319.     switch (info->state) {
  320.     case RANDOM_CHECK:        // check for randomness ... 
  321.             // random is the current option  - so restart the module
  322.             if ( params->controlValues[1])  {    
  323.                 DoClose(storage, blankRgn, params);    // ditch the storage
  324.                 return RestartMe;                    // tell AD to reinit us
  325.             } else info->state = STATE_DOWN;        // not random?, then move on
  326.             break;
  327.     case STATE_DOWN:
  328.             do_some_knocking(info, params);
  329.             break;
  330.     case STATE_GOING_UP:
  331.             slide_picture_up(info, params);        
  332.             break;
  333.     case STATE_UP:
  334.             info->state = STATE_LOOKING;
  335.             break;
  336.     case STATE_LOOKING:
  337.             slide_eyes_around(info, params);
  338.             break;        
  339.     case STATE_GOING_DOWN:
  340.             slide_picture_down(info, blankRgn,  params);
  341.             break;
  342.     default:
  343.         info->state = STATE_DOWN; // this should not happen
  344.         break;
  345.     }
  346.     HUnlock(storage);
  347.     return noErr;
  348. }
  349. //////////////////////////////////////////////////////////////////////////////////////
  350. // this is called when they click on something in the control panel
  351. OSErr 
  352. DoSetUp(RgnHandle blankRgn, short message, GMParamBlockPtr params) {
  353.  
  354.     return noErr;
  355. }
  356.  
  357.  
  358. void
  359. slide_eyes_around(infostructPtr info, GMParamBlockPtr params)
  360. {
  361.  
  362.     // if there are eyes, eyesleft, eyesright, an eyes point *AND* a random chance
  363.     // then go ahead and play with the eyes
  364.     if (info->eyes != (PicHandle)nil &&
  365.             info->eyesleft != (PicHandle)nil &&
  366.                 info->eyesright != (PicHandle)nil &&
  367.                     info->eyesPt.h != -1 &&
  368.                     info->eyesPt.v != -1 &&
  369.                     (!(Random()%10)) ) {
  370.         Rect r;
  371.         short tempnum;
  372.         
  373.         r = (*info->eyes)->picFrame;
  374.         // what if the picFrame is not 0,0 origined? 
  375.  
  376.         // offset to where the pixmap's rect actually is on screen
  377.         OffsetRect( &r, info->theRect.left, info->theRect.top);
  378.         
  379.         // offset to where the eyes resource says it is
  380.         OffsetRect( &r, info->eyesPt.h, info->eyesPt.v); 
  381.         
  382.         // randomly choose which eye pict to display
  383.         tempnum = RangedRdm(0, 4);        // was 5 ... I like things a bit more abnormal
  384.         switch(tempnum) {
  385.             case 0:  DrawPicture( info->eyesleft, &r); break;
  386.             case 1:  DrawPicture( info->eyesright, &r); break;
  387.             // case 2, 3, 4, 5 ... all do normal eye things in the default
  388.             default: DrawPicture( info->eyes, &r); break;
  389.         }
  390.     }
  391.     
  392.     // make some noise, also?
  393.     if (!SoundBusy(info->soundInfo, params->sndChannel) && 
  394.             (info->faceSound != (Handle)nil)  &&
  395.              (!(Random()%100)) ) {
  396.             
  397.             PlaySound( info->soundInfo, params->sndChannel, info->faceSound);
  398.     }
  399.  
  400.  
  401.     // random chance to stop all this peering about and start sliding down
  402.     if (!(Random()%300) ) info->state = STATE_GOING_DOWN;
  403.     
  404. }
  405.  
  406.  
  407. void
  408. slide_picture_up(infostructPtr info, GMParamBlockPtr params)  {
  409.     Boolean *synchFlag;        /* pointer to speed up access to synch */
  410.     short DELTA;
  411.     GWorldPtr    worldPtr;        // temp ptr to help address stuff
  412.     GWorldPtr    currPort;        // something to save the port + device
  413.     GDHandle    currDev;
  414.             
  415.     // amount of pixels to slide is 1/5 the slider value ( {0..100} => {0..20} )
  416.     DELTA = 1 + params->controlValues[0] / 5;
  417.     
  418.     // if this is the first time, then setup theRect (where to draw on the screen)
  419.     if (info->theRect.top == 0 && info->theRect.left == 0) {
  420.         short leftrand;
  421.         // random horizontal offset on the screen so we don't always slide in 
  422.         // up from the same place
  423.         leftrand = RangedRdm( 0, (info->theScreen.right - info->theScreen.left)/2);
  424.         OffsetRect( &(info->theRect), 
  425.                 (info->theScreen).left + leftrand,  (info->theScreen).bottom);
  426.     }
  427.     
  428.     // slide them up a DELTA amount
  429.     OffsetRect( &(info->theRect), 0, -DELTA);
  430.     
  431.     // if they've bumped the top, or moved up so far that their bottom is above
  432.     // the screen's bottom, 
  433.     // or if they've moved so the eyes show and random chance
  434.     // it's time to stop moving up all together
  435.     
  436.     if ( (info->theRect.top <= info->theScreen.top) ||
  437.             (info->theRect.bottom <= info->theScreen.bottom) ||
  438.                 // if we're up past where the eyes show ... then randomly stop here
  439.                 (((info->theRect.top + info->eyesPt.v +
  440.                     ((*info->eyes)->picFrame.bottom - (*info->eyes)->picFrame.top ))
  441.                     < info->theScreen.bottom) && 
  442.                     (info->eyesPt.v != -1) &&
  443.                     !(Random()%20))
  444.             ) 
  445.     {
  446.         OffsetRect( &(info->theRect), 0, DELTA);    // move it back down a bit
  447.         info->state = STATE_UP;                        // we're all the way up now
  448.     } else {
  449.         PixMapHandle    pixBase, screenBase;
  450.  
  451.         worldPtr = info->gMyOffG;
  452.         GetGWorld(&currPort,&currDev);
  453.         
  454.         ForeColor (blackColor);
  455.         BackColor (whiteColor);
  456.         
  457.         pixBase = GetGWorldPixMap( worldPtr );
  458.         screenBase = GetGWorldPixMap( (GWorldPtr)currPort);
  459.         LockPixels ( pixBase );
  460.         LockPixels ( screenBase);
  461.         
  462.         // wait for vertical retrace
  463.         SynchVBL(0);
  464.         // blit it into place onscreen
  465.         CopyBits ( (BitMap *) (*pixBase),
  466.                     &((GrafPtr)currPort)->portBits, 
  467.                                                                     //&info->theRect, 
  468.                     &(worldPtr->portRect),
  469.                     &info->theRect, 
  470.                     srcCopy, nil);
  471.         UnlockPixels(pixBase);
  472.         UnlockPixels(screenBase);
  473.     }
  474. }
  475.  
  476. void
  477. slide_picture_down(infostructPtr info, RgnHandle blankRgn, GMParamBlockPtr params)  {
  478.     Boolean *synchFlag;        /* pointer to speed up access to synch */
  479.     Rect diffRect;
  480.     short DELTA;
  481.     GWorldPtr    worldPtr;        // temp ptr to help address stuff
  482.     GWorldPtr    currPort;        // something to save the port + device
  483.     GDHandle    currDev;
  484.     
  485.     DELTA = 1 + params->controlValues[0] / 5;
  486.     
  487.     OffsetRect( &(info->theRect), 0, DELTA);        // slide downward
  488.     
  489.     // if we've slid so far down that our top leaves the screen, we're done going down
  490.     if ( info->theRect.top >= info->theScreen.bottom) {
  491.         // new change ... time to do RANDOM check
  492.         //info->state = STATE_DOWN;    
  493.         info->state = RANDOM_CHECK;        // we've slid off the screen - random?
  494.         
  495.         // I'm anal retentive, so let's just make sure the screen if cleared...
  496.         FillRgn(blankRgn, params->qdGlobalsCopy->qdBlack);
  497.         // set the rect to 0,0 offset so we recognize the initial condition in slide_up
  498.         SetRect( &(info->theRect), 0, 0, info->thePictWidth, info->thePictHeight);
  499.     } else {
  500.         PixMapHandle    pixBase, screenBase;
  501.         
  502.         worldPtr = info->gMyOffG;
  503.         GetGWorld(&currPort,&currDev);
  504.     
  505.         ForeColor (blackColor);
  506.         BackColor (whiteColor);
  507.         
  508.         pixBase = GetGWorldPixMap( worldPtr);
  509.         screenBase = GetGWorldPixMap( (GWorldPtr)currPort);
  510.         LockPixels ( pixBase );
  511.         LockPixels ( screenBase);
  512.         
  513.         // wait for vertical retrace
  514.         SynchVBL(0);
  515.  
  516.         CopyBits ( (BitMap *) (*(worldPtr->portPixMap)),
  517.                     &((GrafPtr)currPort)->portBits, 
  518.                     &(worldPtr->portRect),
  519.                     &info->theRect, 
  520.                     srcCopy, nil);
  521.                     
  522.         UnlockPixels(pixBase);
  523.         UnlockPixels(screenBase);
  524.     }
  525. }
  526.  
  527.  
  528. // face is offscreen ... so it knocks on the glass a bit.
  529. void
  530. do_some_knocking(infostructPtr temp, GMParamBlockPtr params) {
  531.  
  532.     
  533.     
  534.     // if it is time to make noise again ...
  535.     if (TickCount() >= temp->nextSoundTick) {
  536.         // if it's not busy and we have sound and we have a sound resource, then do it
  537.         if (!SoundBusy(temp->soundInfo, params->sndChannel) && 
  538.                 (temp->oneKnockSound != (Handle)nil) )
  539.         {
  540.             short i, knocks;
  541.             long tempticks;
  542.             
  543.             // random number of knocks
  544.             knocks = RangedRdm(2, 6);
  545.             for (i=0; i<=knocks; i++) {
  546.                 PlaySound( temp->soundInfo, params->sndChannel, temp->oneKnockSound);
  547.                 // delay a random amount to give it some "human" like feel
  548.                 Delay(     RangedRdm(7, 12), &tempticks);
  549.                 
  550.             }
  551.             // lets not make sound until some amount later {5..15} seconds
  552.             temp->nextSoundTick = TickCount() + RangedRdm(300, 900);
  553.         }
  554.     } 
  555.     
  556.     // random chance to just stop all this knocking and start the show
  557.     if (!(Random()%200)) {
  558.         temp->nextSoundTick = 0;
  559.         temp->state = STATE_GOING_UP;
  560.     }
  561. }
  562.  
  563.  
  564.  
  565. OSErr DoSelected(RgnHandle blankRgn, short message, GMParamBlockPtr params)
  566. {
  567.     // I tried playing with params here and they don't seem instantiated,
  568.     // so don't play too much in this routine
  569.     return noErr;
  570. }
  571.  
  572.  
  573. // this is from the Think C reference code example ...
  574. unsigned short RangedRdm( unsigned short min, unsigned short max )
  575. /* assume that min is less than max */
  576. {
  577.     // uh ... not this isn't quite right - it's between 0 and 65535, not 65536
  578.     unsigned    qdRdm;    /* treat return value as 0-65536 */
  579.     long    range, t;
  580.     
  581.     // just to be safe, I'll put this here
  582.     if (min > max) DebugStr("\pMin greater then Max in RangedRdm");
  583.     
  584.     qdRdm = Random();
  585.     range = max - min;
  586.     // max - min gives us the the difference between max and min ... that is 
  587.     // not inclusive. It gives us { min <= range < max }
  588.     // so we never see that max number!!
  589.     range++;
  590.     t = ((long)qdRdm * range) / 65536;     /* now 0 <= t <= range */
  591.     return( t+min );
  592. }
  593.  
  594.  
  595.  
  596. OSErr DoAboutBox(RgnHandle blankRgn, short message, GMParamBlockPtr params)
  597. {
  598.     return noErr;
  599. }
  600.